﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using ttlang;

namespace ttlang.builder.cs
{
    static class ProjectExporter
    {
        /// <summary>
        /// 导出 .csproj
        /// </summary>
        public static void ExportCSProjFile(string path, ProjectOption.ProjectType outputType)
        {
            string str = "";

            XmlDocument xml = new XmlDocument();
            //项目名字（文件夹名）
            var arr = path.Split("\\");
            var projName = arr[arr.Length - 2];
            //导出路径
            var savePath = path + projName + ".csproj";

            //拼接
            //更节点
            var Project = xml.CreateElement("Project");
            xml.AppendChild(Project);
            Project.SetAttribute("Sdk", "Microsoft.NET.Sdk");
            //PropertyGroup
            var PropertyGroup = xml.CreateElement("PropertyGroup");
            Project.AppendChild(PropertyGroup);
            //输出类型
            var OutputType = xml.CreateElement("OutputType");
            PropertyGroup.AppendChild(OutputType);
            OutputType.InnerText = outputType == ProjectOption.ProjectType.EXE ? "Exe" : "Library";
            //.net 目标框架
            var TargetFramework = xml.CreateElement("TargetFramework");
            PropertyGroup.AppendChild(TargetFramework);
            TargetFramework.InnerText = "netcoreapp3.1";     //临时 core 3.1

            var AllowUnsafeBlocks = xml.CreateElement("AllowUnsafeBlocks");
            PropertyGroup.AppendChild(AllowUnsafeBlocks);
            AllowUnsafeBlocks.InnerText = "True"; 
            //获取字符串
            using (var m = new System.IO.MemoryStream())
            {
                var writer = new XmlTextWriter(m, Encoding.UTF8);
                writer.Formatting = Formatting.Indented;
                xml.Save(writer);
                //
                using (var reader = new System.IO.StreamReader(m, Encoding.UTF8))
                {
                    m.Position = 0;
                    str = reader.ReadToEnd();
                }
            }

            //.csproj 保存成文件

            if (System.IO.File.Exists(savePath))
                System.IO.File.Delete(savePath);
            System.IO.File.WriteAllBytes(savePath, Encoding.UTF8.GetBytes(str));
        }
        public static void ExportCSProjBaseLib(string path)
        {
            var _arrayname = System.IO.Path.Combine(path, "_array.cs");
            System.IO.File.WriteAllText(_arrayname, limitarray);
            var _consolename = System.IO.Path.Combine(path, "_console.cs");
            System.IO.File.WriteAllText(_consolename, console);
        }

        /// <summary>
        /// 导出 tsconfig.json
        /// </summary>
        public static void ExportTSProjFile(string path, ProjectOption.ProjectType outputType)
        {
            var str = "";
            //导出路径
            var savePath = path  + "tsconfig.json";

            //module : system  是将目录下的所有.ts 文件 全部生成到 outFile所对应的路径 main.js文件中
            //         Commonjs 各自的.ts文件 生成各自对应的.js文件，生成的目标路径为 outDir
            //   ""outDir"": ""./ bin / "",
            //拼接
            //需要有个outDir,否则容易冲突
            str = @"{
    ""compilerOptions"": {
        ""module"": ""system"",
        ""target"": ""es5"",
        ""sourceMap"": false,
        ""outFile"": ""./bin/main.js"",
        ""outDir"":""./bin/"",
        ""removeComments"": true,
        ""declaration"": true,
        ""lib"": [
            ""dom"",
            ""es2015.promise"",
            ""es2015""
        ]
    }
}";

            //tsconfig.json 保存成文件

            if (System.IO.File.Exists(savePath))
                System.IO.File.Delete(savePath);
            System.IO.File.WriteAllBytes(savePath, Encoding.UTF8.GetBytes(str));
            //System.IO.File.WriteAllText(savePath, str);
        }


        public static void ExportTSProjHtml(string path)
        {
            var _indexHtml = System.IO.Path.Combine(path, "index.html");
            System.IO.File.WriteAllText(_indexHtml, indexHtml);
        }
        
        //完全没必要
        //public static void ExportTSProjSystem(string path)
        //{
        //    var _systemSrc = System.IO.Path.Combine(path, "system.src.js");
        //    System.IO.File.WriteAllText(_systemSrc, systemSrc);
        //}

        public static string limitarray = @"
using System;
namespace ttbase
{
    class TTArray<type> : ICloneable
    {
        int _length;
        type[] array;

        public TTArray(int maxlength)
        {
            array = new type[maxlength];
        }
        public int Length
        {
            get
            {
                return _length;
            }
            set
            {
                if (value >= array.Length || value < 0)
                    throw new Exception(""out of range."");
                _length = value;
            }
        }
        public int MaxLength
        {
            get
            {
                return array.Length;
            }
        }
        public type this[int index]
        {
            get
            {
                if (index >= _length || index < 0)
                    throw new Exception(""out of range."");
                return array[index];
            }
            set
            {
                if (index >= _length || index < 0)
                    throw new Exception(""out of range."");
                array[index] = value;
            }
        }
        public void Clear()
        {
            _length = 0;
        }
        public void Append(TTArray<type> arr)
        {
            int newlength = Math.Min(this._length + arr.Length, this.MaxLength);
            for (var i = _length; i < newlength; i++)
            {
                this.array[i] = arr[i - _length];
            }
            this._length = newlength;

        }
        public override string ToString()
        {
            unsafe
            {
                if (typeof(type) == typeof(UInt16))
                {
                    fixed (void* p = (UInt16[])(object)array)
                    {
                        return new string((char*)p, 0, this._length);
                    }
                }
                else if (typeof(type) == typeof(char))
                {

                    fixed (char* p = (char[])(object)array)
                    {
                        return new string(p, 0, this._length);
                    }
                }
                else
                {
                    return ""TTArray<"" + typeof(type).Name + "">["" + _length + "",max="" + array.Length + ""]"";
                }
            }
        }
        public object Clone()
        {
            var arr = new TTArray<type>(MaxLength);
            arr.Length = this._length;
            for (var i = 0; i < _length; i++)
            {
                arr[i] = this.array[i];
            }
            return arr;
        }
    }
}

";
        public static string console = @"
using System;
namespace ttbase
{
    static class TTConsole
    {
        public static void Log(string str)
        {
            Console.ForegroundColor = ConsoleColor.White;
            System.Console.WriteLine(str);
        }
        public static void Warn(string str)
        {
            Console.ForegroundColor = ConsoleColor.Yellow;
            System.Console.WriteLine(str);
        }
        public static void Error(string str)
        {
            Console.ForegroundColor = ConsoleColor.Red;
            System.Console.WriteLine(str);
        }
        public static void Log(object obj)
        {
            Console.ForegroundColor = ConsoleColor.White;
            System.Console.WriteLine(obj.ToString());
        }
        public static void Warn(object obj)
        {
            Console.ForegroundColor = ConsoleColor.Yellow;
            System.Console.WriteLine(obj.ToString());
        }
        public static void Error(object obj)
        {
            Console.ForegroundColor = ConsoleColor.Red;
            System.Console.WriteLine(obj.ToString());
        }

    }  
}
";
        //<script src=""./ bin / system.src.js""></script>
        public static string indexHtml = @"
<!DOCTYPE html>
<html style=""height: 100%;"">
<head>
    <title>
    </title>
    <meta charset = ""utf-8"" />
   
    <script src = ""./bin/main.js"" ></script>
    <script>
        window.onload = function() {
            hi.Main(); //这个这样写死肯定是不对的,回头要保证入口点固定
        }

    </script>
</head>
</html>";
    }
}
namespace ttbase
{
    static class TTConsole
    {
        public static void Log(string str)
        {
            Console.ForegroundColor = ConsoleColor.White;
            System.Console.WriteLine(str);
        }
        public static void Warn(string str)
        {
            Console.ForegroundColor = ConsoleColor.Yellow;
            System.Console.WriteLine(str);
        }
        public static void Error(string str)
        {
            Console.ForegroundColor = ConsoleColor.Red;
            System.Console.WriteLine(str);
        }
        public static void Log(object obj)
        {
            Console.ForegroundColor = ConsoleColor.White;
            System.Console.WriteLine(obj.ToString());
        }
        public static void Warn(object obj)
        {
            Console.ForegroundColor = ConsoleColor.Yellow;
            System.Console.WriteLine(obj.ToString());
        }
        public static void Error(object obj)
        {
            Console.ForegroundColor = ConsoleColor.Red;
            System.Console.WriteLine(obj.ToString());
        }

    }
    class TTArray<type> : ICloneable
    {
        int _length;
        type[] array;

        public TTArray(int maxlength)
        {
            array = new type[maxlength];
        }
        public int Length
        {
            get
            {
                return _length;
            }
            set
            {
                if (value >= array.Length || value < 0)
                    throw new Exception("out of range.");
                _length = value;
            }
        }
        public int MaxLength
        {
            get
            {
                return array.Length;
            }
        }
        public type this[int index]
        {
            get
            {
                if (index >= _length || index < 0)
                    throw new Exception("out of range.");
                return array[index];
            }
            set
            {
                if (index >= _length || index < 0)
                    throw new Exception("out of range.");
                array[index] = value;
            }
        }
        public void Clear()
        {
            _length = 0;
        }
        public void Append(TTArray<type> arr)
        {
            int newlength = Math.Min(this._length + arr.Length, this.MaxLength);
            for (var i = _length; i < newlength; i++)
            {
                this.array[i] = arr[i - _length];
            }
            this._length = newlength;

        }
        public override string ToString()
        {
            unsafe
            {
                if (typeof(type) == typeof(UInt16))
                {
                    fixed (void* p = (UInt16[])(object)array)
                    {
                        return new string((char*)p, 0, this._length);
                    }
                }
                else if (typeof(type) == typeof(char))
                {

                    fixed (char* p = (char[])(object)array)
                    {
                        return new string(p, 0, this._length);
                    }
                }
                else
                {
                    return "TTArray<" + typeof(type).Name + ">[" + _length + ",max=" + array.Length + "]";
                }
            }
        }
        public object Clone()
        {
            var arr = new TTArray<type>(MaxLength);
            arr.Length = this._length;
            for (var i = 0; i < _length; i++)
            {
                arr[i] = this.array[i];
            }
            return arr;
        }
    }
}
